home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / cvs-1.8 / cvs-1 / cvs-1.8.1 / src / checkout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-06  |  22.9 KB  |  890 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.4 kit.
  7.  * 
  8.  * Create Version
  9.  * 
  10.  * "checkout" creates a "version" of an RCS repository.  This version is owned
  11.  * totally by the user and is actually an independent copy, to be dealt with
  12.  * as seen fit.  Once "checkout" has been called in a given directory, it
  13.  * never needs to be called again.  The user can keep up-to-date by calling
  14.  * "update" when he feels like it; this will supply him with a merge of his
  15.  * own modifications and the changes made in the RCS original.  See "update"
  16.  * for details.
  17.  * 
  18.  * "checkout" can be given a list of directories or files to be updated and in
  19.  * the case of a directory, will recursivley create any sub-directories that
  20.  * exist in the repository.
  21.  * 
  22.  * When the user is satisfied with his own modifications, the present version
  23.  * can be committed by "commit"; this keeps the present version in tact,
  24.  * usually.
  25.  * 
  26.  * The call is cvs checkout [options] <module-name>...
  27.  * 
  28.  * "checkout" creates a directory ./CVS, in which it keeps its administration,
  29.  * in two files, Repository and Entries. The first contains the name of the
  30.  * repository.  The second contains one line for each registered file,
  31.  * consisting of the version number it derives from, its time stamp at
  32.  * derivation time and its name.  Both files are normal files and can be
  33.  * edited by the user, if necessary (when the repository is moved, e.g.)
  34.  */
  35.  
  36. #include "cvs.h"
  37.  
  38. static char *findslash PROTO((char *start, char *p));
  39. static int build_dirs_and_chdir PROTO((char *dir, char *prepath, char *realdir,
  40.                  int sticky));
  41. static int checkout_proc PROTO((int *pargc, char **argv, char *where,
  42.                   char *mwhere, char *mfile, int shorten,
  43.                   int local_specified, char *omodule,
  44.                   char *msg));
  45. static int safe_location PROTO((void));
  46.  
  47. static const char *const checkout_usage[] =
  48. {
  49.     "Usage:\n  %s %s [-ANPcflnps] [-r rev | -D date] [-d dir] [-k kopt] modules...\n",
  50.     "\t-A\tReset any sticky tags/date/kopts.\n",
  51.     "\t-N\tDon't shorten module paths if -d specified.\n",
  52.     "\t-P\tPrune empty directories.\n",
  53.     "\t-c\t\"cat\" the module database.\n",
  54.     "\t-f\tForce a head revision match if tag/date not found.\n",
  55.     "\t-l\tLocal directory only, not recursive\n",
  56.     "\t-n\tDo not run module program (if any).\n",
  57.     "\t-p\tCheck out files to standard output.\n",
  58.     "\t-s\tLike -c, but include module status.\n",
  59.     "\t-r rev\tCheck out revision or tag. (implies -P)\n",
  60.     "\t-D date\tCheck out revisions as of date. (implies -P)\n",
  61.     "\t-d dir\tCheck out into dir instead of module name.\n",
  62.     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
  63.     "\t-j rev\tMerge in changes made between current revision and rev.\n",
  64.     NULL
  65. };
  66.  
  67. static const char *const export_usage[] =
  68. {
  69.     "Usage: %s %s [-NPfln] [-r rev | -D date] [-d dir] [-k kopt] module...\n",
  70.     "\t-N\tDon't shorten module paths if -d specified.\n",
  71.     "\t-f\tForce a head revision match if tag/date not found.\n",
  72.     "\t-l\tLocal directory only, not recursive\n",
  73.     "\t-n\tDo not run module program (if any).\n",
  74.     "\t-r rev\tCheck out revision or tag.\n",
  75.     "\t-D date\tCheck out revisions as of date.\n",
  76.     "\t-d dir\tCheck out into dir instead of module name.\n",
  77.     "\t-k kopt\tUse RCS kopt -k option on checkout.\n",
  78.     NULL
  79. };
  80.  
  81. static int checkout_prune_dirs;
  82. static int force_tag_match = 1;
  83. static int pipeout;
  84. static int aflag;
  85. static char *options = NULL;
  86. static char *tag = NULL;
  87. static int tag_validated = 0;
  88. static char *date = NULL;
  89. static char *join_rev1 = NULL;
  90. static char *join_rev2 = NULL;
  91. static char *preload_update_dir = NULL;
  92.  
  93. int
  94. checkout (argc, argv)
  95.     int argc;
  96.     char **argv;
  97. {
  98.     int i;
  99.     int c;
  100.     DBM *db;
  101.     int cat = 0, err = 0, status = 0;
  102.     int run_module_prog = 1;
  103.     int local = 0;
  104.     int shorten = -1;
  105.     char *where = NULL;
  106.     char *valid_options;
  107.     const char *const *valid_usage;
  108.     enum mtype m_type;
  109.  
  110.     /*
  111.      * A smaller subset of options are allowed for the export command, which
  112.      * is essentially like checkout, except that it hard-codes certain
  113.      * options to be default (like -kv) and takes care to remove the CVS
  114.      * directory when it has done its duty
  115.      */
  116.     if (strcmp (command_name, "export") == 0)
  117.     {
  118.         m_type = EXPORT;
  119.     valid_options = "Nnk:d:flRQqr:D:";
  120.     valid_usage = export_usage;
  121.     }
  122.     else
  123.     {
  124.         m_type = CHECKOUT;
  125.     valid_options = "ANnk:d:flRpQqcsr:D:j:P";
  126.     valid_usage = checkout_usage;
  127.     }
  128.  
  129.     if (argc == -1)
  130.     usage (valid_usage);
  131.  
  132.     ign_setup ();
  133.     wrap_setup ();
  134.  
  135.     optind = 1;
  136.     while ((c = getopt (argc, argv, valid_options)) != -1)
  137.     {
  138.     switch (c)
  139.     {
  140.         case 'A':
  141.         aflag = 1;
  142.         break;
  143.         case 'N':
  144.         shorten = 0;
  145.         break;
  146.         case 'k':
  147.         if (options)
  148.             free (options);
  149.         options = RCS_check_kflag (optarg);
  150.         break;
  151.         case 'n':
  152.         run_module_prog = 0;
  153.         break;
  154.         case 'Q':
  155.         case 'q':
  156. #ifdef SERVER_SUPPORT
  157.         /* The CVS 1.5 client sends these options (in addition to
  158.            Global_option requests), so we must ignore them.  */
  159.         if (!server_active)
  160. #endif
  161.             error (1, 0,
  162.                "-q or -Q must be specified before \"%s\"",
  163.                command_name);
  164.         break;
  165.         case 'l':
  166.         local = 1;
  167.         break;
  168.         case 'R':
  169.         local = 0;
  170.         break;
  171.         case 'P':
  172.         checkout_prune_dirs = 1;
  173.         break;
  174.         case 'p':
  175.         pipeout = 1;
  176.         run_module_prog = 0;    /* don't run module prog when piping */
  177.         noexec = 1;        /* so no locks will be created */
  178.         break;
  179.         case 'c':
  180.         cat = 1;
  181.         break;
  182.         case 'd':
  183.         where = optarg;
  184.         if (shorten == -1)
  185.             shorten = 1;
  186.         break;
  187.         case 's':
  188.         status = 1;
  189.         break;
  190.         case 'f':
  191.         force_tag_match = 0;
  192.         break;
  193.         case 'r':
  194.         tag = optarg;
  195.         checkout_prune_dirs = 1;
  196.         break;
  197.         case 'D':
  198.         date = Make_Date (optarg);
  199.         checkout_prune_dirs = 1;
  200.         break;
  201.         case 'j':
  202.         if (join_rev2)
  203.             error (1, 0, "only two -j options can be specified");
  204.         if (join_rev1)
  205.             join_rev2 = optarg;
  206.         else
  207.             join_rev1 = optarg;
  208.         break;
  209.         case '?':
  210.         default:
  211.         usage (valid_usage);
  212.         break;
  213.     }
  214.     }
  215.     argc -= optind;
  216.     argv += optind;
  217.  
  218.     if (shorten == -1)
  219.     shorten = 0;
  220.  
  221.     if ((!(cat + status) && argc == 0) || ((cat + status) && argc != 0)
  222.     || (tag && date))
  223.     usage (valid_usage);
  224.  
  225.     if (where && pipeout)
  226.     error (1, 0, "-d and -p are mutually exclusive");
  227.  
  228.     if (strcmp (command_name, "export") == 0)
  229.     {
  230.     if (!tag && !date)
  231.     {
  232.         error (0, 0, "must specify a tag or date");
  233.         usage (valid_usage);
  234.     }
  235.     if (tag && isdigit (tag[0]))
  236.         error (1, 0, "tag `%s' must be a symbolic tag", tag);
  237. /*
  238.  * mhy 950615: -kv doesn't work for binaries with RCS keywords.
  239.  * Instead use the default provided in the RCS file (-ko for binaries).
  240.  */
  241. #if 0
  242.     if (!options)
  243.       options = RCS_check_kflag ("v");/* -kv is default */
  244. #endif
  245.     }
  246.  
  247.     if (!safe_location()) {
  248.         error(1, 0, "Cannot check out files into the repository itself");
  249.     }
  250.  
  251. #ifdef CLIENT_SUPPORT
  252.     if (client_active)
  253.     {
  254.     int expand_modules;
  255.  
  256.     start_server ();
  257.  
  258.     ign_setup ();
  259.     
  260.     /* We have to expand names here because the "expand-modules"
  261.            directive to the server has the side-effect of having the
  262.            server send the check-in and update programs for the
  263.            various modules/dirs requested.  If we turn this off and
  264.            simply request the names of the modules and directories (as
  265.            below in !expand_modules), those files (CVS/Checking.prog
  266.            or CVS/Update.prog) don't get created.  Grrr.  */
  267.     
  268.     expand_modules = (!cat && !status && !pipeout
  269.               && supported_request ("expand-modules"));
  270.     
  271.     if (expand_modules)
  272.       {
  273.         /* This is done here because we need to read responses
  274.                from the server before we send the command checkout or
  275.                export files. */
  276.  
  277.         client_expand_modules (argc, argv, local);
  278.       }
  279.  
  280.     if (!run_module_prog) send_arg ("-n");
  281.     if (local) send_arg ("-l");
  282.     if (pipeout) send_arg ("-p");
  283.     if (!force_tag_match) send_arg ("-f");
  284.     if (aflag)
  285.         send_arg("-A");
  286.     if (!shorten)
  287.         send_arg("-N");
  288.     if (checkout_prune_dirs && strcmp (command_name, "export") != 0)
  289.         send_arg("-P");
  290.     client_prune_dirs = checkout_prune_dirs;
  291.     if (cat)
  292.         send_arg("-c");
  293.     if (where != NULL)
  294.     {
  295.         option_with_arg ("-d", where);
  296.     }
  297.     if (status)
  298.         send_arg("-s");
  299.     if (strcmp (command_name, "export") != 0
  300.         && options != NULL
  301.         && options[0] != '\0')
  302.         send_arg (options);
  303.     option_with_arg ("-r", tag);
  304.     if (date)
  305.         client_senddate (date);
  306.     if (join_rev1 != NULL)
  307.         option_with_arg ("-j", join_rev1);
  308.     if (join_rev2 != NULL)
  309.         option_with_arg ("-j", join_rev2);
  310.  
  311.     if (expand_modules)
  312.       {
  313.         client_send_expansions (local);
  314.       }
  315.     else
  316.       {
  317.         int i;
  318.         for (i = 0; i < argc; ++i)
  319.           send_arg (argv[i]);
  320.         client_nonexpanded_setup ();
  321.       }
  322.  
  323.     send_to_server (strcmp (command_name, "export") == 0 ?
  324.                         "export\012" : "co\012",
  325.                         0);
  326.  
  327.     return get_responses_and_close ();
  328.     }
  329. #endif /* CLIENT_SUPPORT */
  330.  
  331.     if (cat || status)
  332.     {
  333.     cat_module (status);
  334.     return (0);
  335.     }
  336.     db = open_module ();
  337.  
  338.     /*
  339.      * if we have more than one argument and where was specified, we make the
  340.      * where, cd into it, and try to shorten names as much as possible.
  341.      * Otherwise, we pass the where as a single argument to do_module.
  342.      */
  343.     if (argc > 1 && where != NULL)
  344.     {
  345.     char repository[PATH_MAX];
  346.  
  347.     (void) CVS_MKDIR (where, 0777);
  348.     if (chdir (where) < 0)
  349.         error (1, errno, "cannot chdir to %s", where);
  350.     preload_update_dir = xstrdup (where);
  351.     where = (char *) NULL;
  352.     if (!isfile (CVSADM))
  353.     {
  354.         (void) sprintf (repository, "%s/%s/%s", CVSroot, CVSROOTADM,
  355.                 CVSNULLREPOS);
  356.         if (!isfile (repository))
  357.         {
  358.         mode_t omask;
  359.         omask = umask (cvsumask);
  360.         (void) CVS_MKDIR (repository, 0777);
  361.         (void) umask (omask);
  362.         }
  363.  
  364.         /* I'm not sure whether this check is redundant.  */
  365.         if (!isdir (repository))
  366.         error (1, 0, "there is no repository %s", repository);
  367.  
  368.         Create_Admin (".", where, repository,
  369.               (char *) NULL, (char *) NULL);
  370.         if (!noexec)
  371.         {
  372.         FILE *fp;
  373.  
  374.         fp = open_file (CVSADM_ENTSTAT, "w+");
  375.         if (fclose(fp) == EOF)
  376.             error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
  377. #ifdef SERVER_SUPPORT
  378.         if (server_active)
  379.             server_set_entstat (preload_update_dir, repository);
  380. #endif
  381.         }
  382.     }
  383.     }
  384.  
  385.     /*
  386.      * if where was specified (-d) and we have not taken care of it already
  387.      * with the multiple arg stuff, and it was not a simple directory name
  388.      * but rather a path, we strip off everything but the last component and
  389.      * attempt to cd to the indicated place.  where then becomes simply the
  390.      * last component
  391.      */
  392.     if (where != NULL && strchr (where, '/') != NULL)
  393.     {
  394.     char *slash;
  395.  
  396.     slash = strrchr (where, '/');
  397.     *slash = '\0';
  398.  
  399.     if (chdir (where) < 0)
  400.         error (1, errno, "cannot chdir to %s", where);
  401.  
  402.     preload_update_dir = xstrdup (where);
  403.  
  404.     where = slash + 1;
  405.     if (*where == '\0')
  406.         where = NULL;
  407.     }
  408.  
  409.     for (i = 0; i < argc; i++)
  410.     err += do_module (db, argv[i], m_type, "Updating", checkout_proc,
  411.               where, shorten, local, run_module_prog,
  412.               (char *) NULL);
  413.     close_module (db);
  414.     return (err);
  415. }
  416.  
  417. static int
  418. safe_location ()
  419. {
  420.     char current[PATH_MAX];
  421.     char hardpath[PATH_MAX+5];
  422.     int  x;
  423.  
  424.     x = readlink(CVSroot, hardpath, sizeof hardpath - 1);
  425.     if (x == -1)
  426.     {
  427.         strcpy(hardpath, CVSroot);
  428.     }
  429.     else
  430.     {
  431.         hardpath[x] = '\0';
  432.     }
  433.     getwd (current);
  434.     if (strncmp(current, hardpath, strlen(hardpath)) == 0)
  435.     {
  436.         return (0);
  437.     }
  438.     return (1);
  439. }
  440.  
  441. /*
  442.  * process_module calls us back here so we do the actual checkout stuff
  443.  */
  444. /* ARGSUSED */
  445. static int
  446. checkout_proc (pargc, argv, where, mwhere, mfile, shorten,
  447.            local_specified, omodule, msg)
  448.     int *pargc;
  449.     char **argv;
  450.     char *where;
  451.     char *mwhere;
  452.     char *mfile;
  453.     int shorten;
  454.     int local_specified;
  455.     char *omodule;
  456.     char *msg;
  457. {
  458.     int err = 0;
  459.     int which;
  460.     char *cp;
  461.     char *cp2;
  462.     char repository[PATH_MAX];
  463.     char xwhere[PATH_MAX];
  464.     char *oldupdate = NULL;
  465.     char *prepath;
  466.     char *realdirs;
  467.  
  468.     /*
  469.      * OK, so we're doing the checkout! Our args are as follows: 
  470.      *  argc,argv contain either dir or dir followed by a list of files 
  471.      *  where contains where to put it (if supplied by checkout) 
  472.      *  mwhere contains the module name or -d from module file 
  473.      *  mfile says do only that part of the module
  474.      *  shorten = TRUE says shorten as much as possible 
  475.      *  omodule is the original arg to do_module()
  476.      */
  477.  
  478.     /* set up the repository (maybe) for the bottom directory */
  479.     (void) sprintf (repository, "%s/%s", CVSroot, argv[0]);
  480.  
  481.     /* save the original value of preload_update_dir */
  482.     if (preload_update_dir != NULL)
  483.     oldupdate = xstrdup (preload_update_dir);
  484.  
  485.     /* fix up argv[] for the case of partial modules */
  486.     if (mfile != NULL)
  487.     {
  488.     char file[PATH_MAX];
  489.  
  490.     /* if mfile is really a path, straighten it out first */
  491.     if ((cp = strrchr (mfile, '/')) != NULL)
  492.     {
  493.         *cp = 0;
  494.         (void) strcat (repository, "/");
  495.         (void) strcat (repository, mfile);
  496.  
  497.         /*
  498.          * Now we need to fill in the where correctly. if !shorten, tack
  499.          * the rest of the path onto where if where is filled in
  500.          * otherwise tack the rest of the path onto mwhere and make that
  501.          * the where
  502.          * 
  503.          * If shorten is enabled, we might use mwhere to set where if 
  504.          * nobody set it yet, so we'll need to setup mwhere as the last
  505.          * component of the path we are tacking onto repository
  506.          */
  507.         if (!shorten)
  508.         {
  509.         if (where != NULL)
  510.             (void) sprintf (xwhere, "%s/%s", where, mfile);
  511.         else
  512.             (void) sprintf (xwhere, "%s/%s", mwhere, mfile);
  513.         where = xwhere;
  514.         }
  515.         else
  516.         {
  517.         char *slash;
  518.  
  519.         if ((slash = strrchr (mfile, '/')) != NULL)
  520.             mwhere = slash + 1;
  521.         else
  522.             mwhere = mfile;
  523.         }
  524.         mfile = cp + 1;
  525.     }
  526.  
  527.     (void) sprintf (file, "%s/%s", repository, mfile);
  528.     if (isdir (file))
  529.     {
  530.  
  531.         /*
  532.          * The portion of a module was a directory, so kludge up where to
  533.          * be the subdir, and fix up repository
  534.          */
  535.         (void) strcpy (repository, file);
  536.  
  537.         /*
  538.          * At this point, if shorten is not enabled, we make where either
  539.          * where with mfile concatenated, or if where hadn't been set we
  540.          * set it to mwhere with mfile concatenated.
  541.          * 
  542.          * If shorten is enabled and where hasn't been set yet, then where
  543.          * becomes mfile
  544.          */
  545.         if (!shorten)
  546.         {
  547.         if (where != NULL)
  548.             (void) sprintf (xwhere, "%s/%s", where, mfile);
  549.         else
  550.             (void) sprintf (xwhere, "%s/%s", mwhere, mfile);
  551.         where = xwhere;
  552.         }
  553.         else if (where == NULL)
  554.         where = mfile;
  555.     }
  556.     else
  557.     {
  558.         int i;
  559.  
  560.         /*
  561.          * The portion of a module was a file, so kludge up argv to be
  562.          * correct
  563.          */
  564.         for (i = 1; i < *pargc; i++)/* free the old ones */
  565.         free (argv[i]);
  566.         argv[1] = xstrdup (mfile);    /* set up the new one */
  567.         *pargc = 2;
  568.  
  569.         /* where gets mwhere if where isn't set */
  570.         if (where == NULL)
  571.         where = mwhere;
  572.     }
  573.     }
  574.  
  575.     /*
  576.      * if shorten is enabled and where isn't specified yet, we pluck the last
  577.      * directory component of argv[0] and make it the where
  578.      */
  579.     if (shorten && where == NULL)
  580.     {
  581.     if ((cp = strrchr (argv[0], '/')) != NULL)
  582.     {
  583.         (void) strcpy (xwhere, cp + 1);
  584.         where = xwhere;
  585.     }
  586.     }
  587.  
  588.     /* if where is still NULL, use mwhere if set or the argv[0] dir */
  589.     if (where == NULL)
  590.     {
  591.     if (mwhere)
  592.         where = mwhere;
  593.     else
  594.     {
  595.         (void) strcpy (xwhere, argv[0]);
  596.         where = xwhere;
  597.     }
  598.     }
  599.  
  600.     if (preload_update_dir != NULL)
  601.     {
  602.     char tmp[PATH_MAX];
  603.  
  604.     (void) sprintf (tmp, "%s/%s", preload_update_dir, where);
  605.     free (preload_update_dir);
  606.     preload_update_dir = xstrdup (tmp);
  607.     }
  608.     else
  609.     preload_update_dir = xstrdup (where);
  610.  
  611.     /*
  612.      * At this point, where is the directory we want to build, repository is
  613.      * the repository for the lowest level of the path.
  614.      */
  615.  
  616.     /*
  617.      * If we are sending everything to stdout, we can skip a whole bunch of
  618.      * work from here
  619.      */
  620.     if (!pipeout)
  621.     {
  622.  
  623.     /*
  624.      * We need to tell build_dirs not only the path we want it to build,
  625.      * but also the repositories we want it to populate the path with. To
  626.      * accomplish this, we pass build_dirs a ``real path'' with valid
  627.      * repositories and a string to pre-pend based on how many path
  628.      * elements exist in where. Big Black Magic
  629.      */
  630.     prepath = xstrdup (repository);
  631.     cp = strrchr (where, '/');
  632.     cp2 = strrchr (prepath, '/');
  633.     while (cp != NULL)
  634.     {
  635.         cp = findslash (where, cp - 1);
  636.         cp2 = findslash (prepath, cp2 - 1);
  637.     }
  638.     *cp2 = '\0';
  639.     realdirs = cp2 + 1;
  640.  
  641.     /*
  642.      * build dirs on the path if necessary and leave us in the bottom
  643.      * directory (where if where was specified) doesn't contain a CVS
  644.      * subdir yet, but all the others contain CVS and Entries.Static
  645.      * files
  646.      */
  647.     if (build_dirs_and_chdir (where, prepath, realdirs, *pargc <= 1) != 0)
  648.     {
  649.         error (0, 0, "ignoring module %s", omodule);
  650.         free (prepath);
  651.         free (preload_update_dir);
  652.         preload_update_dir = oldupdate;
  653.         return (1);
  654.     }
  655.  
  656.     /* clean up */
  657.     free (prepath);
  658.  
  659.     /* set up the repository (or make sure the old one matches) */
  660.     if (!isfile (CVSADM))
  661.     {
  662.         FILE *fp;
  663.  
  664.         if (!noexec && *pargc > 1)
  665.         {
  666.         /* I'm not sure whether this check is redundant.  */
  667.         if (!isdir (repository))
  668.             error (1, 0, "there is no repository %s", repository);
  669.  
  670.         Create_Admin (".", where, repository,
  671.                   (char *) NULL, (char *) NULL);
  672.         fp = open_file (CVSADM_ENTSTAT, "w+");
  673.         if (fclose(fp) == EOF)
  674.             error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
  675. #ifdef SERVER_SUPPORT
  676.         if (server_active)
  677.             server_set_entstat (where, repository);
  678. #endif
  679.         }
  680.         else
  681.         {
  682.         /* I'm not sure whether this check is redundant.  */
  683.         if (!isdir (repository))
  684.             error (1, 0, "there is no repository %s", repository);
  685.  
  686.         Create_Admin (".", where, repository, tag, date);
  687.         }
  688.     }
  689.     else
  690.     {
  691.         char *repos;
  692.  
  693.         /* get the contents of the previously existing repository */
  694.         repos = Name_Repository ((char *) NULL, preload_update_dir);
  695.         if (fncmp (repository, repos) != 0)
  696.         {
  697.         error (0, 0, "existing repository %s does not match %s",
  698.                repos, repository);
  699.         error (0, 0, "ignoring module %s", omodule);
  700.         free (repos);
  701.         free (preload_update_dir);
  702.         preload_update_dir = oldupdate;
  703.         return (1);
  704.         }
  705.         free (repos);
  706.     }
  707.     }
  708.  
  709.     /*
  710.      * If we are going to be updating to stdout, we need to cd to the
  711.      * repository directory so the recursion processor can use the current
  712.      * directory as the place to find repository information
  713.      */
  714.     if (pipeout)
  715.     {
  716.     if (chdir (repository) < 0)
  717.     {
  718.         error (0, errno, "cannot chdir to %s", repository);
  719.         free (preload_update_dir);
  720.         preload_update_dir = oldupdate;
  721.         return (1);
  722.     }
  723.     which = W_REPOS;
  724.     if (tag != NULL && !tag_validated)
  725.     {
  726.         tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag, NULL);
  727.         tag_validated = 1;
  728.     }
  729.     }
  730.     else
  731.     {
  732.     which = W_LOCAL | W_REPOS;
  733.     if (tag != NULL && !tag_validated)
  734.     {
  735.         tag_check_valid (tag, *pargc - 1, argv + 1, 0, aflag,
  736.                  repository);
  737.         tag_validated = 1;
  738.     }
  739.     }
  740.  
  741.     if (tag != NULL || date != NULL)
  742.     which |= W_ATTIC;
  743.  
  744.     /* FIXME: We don't call tag_check_valid on join_rev1 and join_rev2
  745.        yet (make sure to handle ':' correctly if we do, though).  */
  746.  
  747.     /*
  748.      * if we are going to be recursive (building dirs), go ahead and call the
  749.      * update recursion processor.  We will be recursive unless either local
  750.      * only was specified, or we were passed arguments
  751.      */
  752.     if (!(local_specified || *pargc > 1))
  753.     {
  754.     if (strcmp (command_name, "export") != 0 && !pipeout)
  755.         history_write ('O', preload_update_dir, tag ? tag : date, where,
  756.                repository);
  757.     err += do_update (0, (char **) NULL, options, tag, date,
  758.               force_tag_match, 0 /* !local */ ,
  759.               1 /* update -d */ , aflag, checkout_prune_dirs,
  760.               pipeout, which, join_rev1, join_rev2,
  761.               preload_update_dir);
  762.     free (preload_update_dir);
  763.     preload_update_dir = oldupdate;
  764.     return (err);
  765.     }
  766.  
  767.     if (!pipeout)
  768.     {
  769.     int i;
  770.     List *entries;
  771.  
  772.     /* we are only doing files, so register them */
  773.     entries = Entries_Open (0);
  774.     for (i = 1; i < *pargc; i++)
  775.     {
  776.         char *line;
  777.         char *user;
  778.         Vers_TS *vers;
  779.  
  780.         user = argv[i];
  781.         vers = Version_TS (repository, options, tag, date, user,
  782.                    force_tag_match, 0, entries, (RCSNode *) NULL);
  783.         if (vers->ts_user == NULL)
  784.         {
  785.         line = xmalloc (strlen (user) + 15);
  786.         (void) sprintf (line, "Initial %s", user);
  787.         Register (entries, user, vers->vn_rcs ? vers->vn_rcs : "0",
  788.               line, vers->options, vers->tag,
  789.               vers->date, (char *) 0);
  790.         free (line);
  791.         }
  792.         freevers_ts (&vers);
  793.     }
  794.  
  795.     Entries_Close (entries);
  796.     }
  797.  
  798.     /* Don't log "export", just regular "checkouts" */
  799.     if (strcmp (command_name, "export") != 0 && !pipeout)
  800.     history_write ('O', preload_update_dir, (tag ? tag : date), where,
  801.                repository);
  802.  
  803.     /* go ahead and call update now that everything is set */
  804.     err += do_update (*pargc - 1, argv + 1, options, tag, date,
  805.               force_tag_match, local_specified, 1 /* update -d */,
  806.               aflag, checkout_prune_dirs, pipeout, which, join_rev1,
  807.               join_rev2, preload_update_dir);
  808.     free (preload_update_dir);
  809.     preload_update_dir = oldupdate;
  810.     return (err);
  811. }
  812.  
  813. static char *
  814. findslash (start, p)
  815.     char *start;
  816.     char *p;
  817. {
  818.     while (p >= start && *p != '/')
  819.     p--;
  820.     if (p < start)
  821.     return (NULL);
  822.     else
  823.     return (p);
  824. }
  825.  
  826. /*
  827.  * build all the dirs along the path to dir with CVS subdirs with appropriate
  828.  * repositories and Entries.Static files
  829.  */
  830. static int
  831. build_dirs_and_chdir (dir, prepath, realdir, sticky)
  832.     char *dir;
  833.     char *prepath;
  834.     char *realdir;
  835.     int sticky;
  836. {
  837.     FILE *fp;
  838.     char repository[PATH_MAX];
  839.     char path[PATH_MAX];
  840.     char path2[PATH_MAX];
  841.     char *slash;
  842.     char *slash2;
  843.     char *cp;
  844.     char *cp2;
  845.  
  846.     (void) strcpy (path, dir);
  847.     (void) strcpy (path2, realdir);
  848.     for (cp = path, cp2 = path2;
  849.     (slash = strchr (cp, '/')) != NULL && (slash2 = strchr (cp2, '/')) != NULL;
  850.      cp = slash + 1, cp2 = slash2 + 1)
  851.     {
  852.     *slash = '\0';
  853.     *slash2 = '\0';
  854.     (void) CVS_MKDIR (cp, 0777);
  855.     if (chdir (cp) < 0)
  856.     {
  857.         error (0, errno, "cannot chdir to %s", cp);
  858.         return (1);
  859.     }
  860.     if (!isfile (CVSADM) && strcmp (command_name, "export") != 0)
  861.     {
  862.         (void) sprintf (repository, "%s/%s", prepath, path2);
  863.         /* I'm not sure whether this check is redundant.  */
  864.         if (!isdir (repository))
  865.         error (1, 0, "there is no repository %s", repository);
  866.         Create_Admin (".", path, repository, sticky ? (char *) NULL : tag,
  867.               sticky ? (char *) NULL : date);
  868.         if (!noexec)
  869.         {
  870.         fp = open_file (CVSADM_ENTSTAT, "w+");
  871.         if (fclose(fp) == EOF)
  872.             error(1, errno, "cannot close %s", CVSADM_ENTSTAT);
  873. #ifdef SERVER_SUPPORT
  874.         if (server_active)
  875.             server_set_entstat (path, repository);
  876. #endif
  877.         }
  878.     }
  879.     *slash = '/';
  880.     *slash2 = '/';
  881.     }
  882.     (void) CVS_MKDIR (cp, 0777);
  883.     if (chdir (cp) < 0)
  884.     {
  885.     error (0, errno, "cannot chdir to %s", cp);
  886.     return (1);
  887.     }
  888.     return (0);
  889. }
  890.